﻿using Newtonsoft.Json.Linq;
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using Newtonsoft.Json;
using System.Xml.Linq;

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        public JToken root;
        private ContextMenuStrip contextMenuStrip;
        private ToolStripMenuItem deleteToolStripMenuItem;

        public Form1()
        {
            InitializeComponent();

            dataGridView1.ColumnCount = 6;
            dataGridView1.Columns[0].Name = "SN";
            dataGridView1.Columns[1].Name = "Path";
            dataGridView1.Columns[2].Name = "DataType";
            dataGridView1.Columns[3].Name = "Type";
            dataGridView1.Columns[4].Name = "UUID";
            dataGridView1.Columns[5].Name = "Description";

            dataGridView1.Columns[1].DefaultCellStyle.BackColor = Color.LightBlue;
            dataGridView1.Columns[5].DefaultCellStyle.BackColor = Color.LightCyan;

            // 初始化上下文菜单和菜单项  
            contextMenuStrip = new ContextMenuStrip();
            deleteToolStripMenuItem = new ToolStripMenuItem("删除");
            deleteToolStripMenuItem.Click += new EventHandler(deleteToolStripMenuItem_Click);
            contextMenuStrip.Items.Add(deleteToolStripMenuItem);

            // 将上下文菜单与 DataGridView 关联  
            dataGridView2.MouseClick += new MouseEventHandler(dataGridView2_MouseClick);

        }
        private void deleteToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // 遍历所有选定的行，并从 DataGridView 中删除它们  
            foreach (DataGridViewRow row in dataGridView2.SelectedRows)
            {
                dataGridView2.Rows.Remove(row);
            }

            // 注意：如果你的 DataGridView 绑定到数据源，你应该从数据源中删除行，而不是从 DataGridView 中删除  
        }

        private void btnLoad_Click(object sender, EventArgs e)
        {
            //MessageBox.Show("Test");
            //dataGridView1.DataSource = getEmpList();


            //dataGridView1.Rows.Add(0, "UINT8", "sensor", "NA", "NA");
            //Datatable
            //DataTable table = new DataTable();
            //table.Columns.Add("ID", typeof(int));
            //table.Columns.Add("NAME", typeof(string));
            //table.Columns.Add("TYPE", typeof(string));

            //for (int i = 0; i < 30; i++)
            //{
            //    table.Rows.Add(i, "TB" + i, "SH" + (20 - i));
            //}
            //dataGridView2.DataSource = table;


            DataGridViewCheckBoxColumn checkBoxColumn = new DataGridViewCheckBoxColumn();
            checkBoxColumn.HeaderText = "OP";
            checkBoxColumn.Name = "CC";
            dataGridView2.Columns.Add(checkBoxColumn);

            dataGridView2.ColumnCount = 4;
            dataGridView2.Columns[1].Name = "SN";
            dataGridView2.Columns[2].Name = "Path";
            dataGridView2.Columns[3].Name = "Type";

            for (int i = 0; i < 30; i++)
            {
                dataGridView2.Rows.Add(i, "Vehicle.E2E.Demo", "STRING");
            }

            //Load tree.
            TreeNode rootNode = new TreeNode("Root");
            TreeNode childNode1 = new TreeNode("Child1");
            TreeNode childNode2 = new TreeNode("Child2");

            rootNode.Nodes.Add(childNode1);
            rootNode.Nodes.Add(childNode2);

            TreeNode childNode1_1 = new TreeNode("Child 1.1");
            TreeNode childNode1_2 = new TreeNode("Child 1.2");

            childNode1.Nodes.Add(childNode1_1);
            childNode2.Nodes.Add(childNode1_2);

            treeView1.Nodes.Add(rootNode);

        }

        protected List<Emp> getEmpList()
        {
            List<Emp> lEmp = new List<Emp>();
            lEmp.Clear();
            for (int i = 0; i < 30; i++)
            {

                Emp oemp = new Emp(1234 + i, "ARIC" + i, "CN");
                lEmp.Add(oemp);
            }

            return lEmp;
        }


        public static void FillTreeView(TreeView treeView, string json)
        {
            JObject jsonObj = JObject.Parse(json);
            TreeNode rootNode = new TreeNode();
            FillTree(rootNode, jsonObj);
            treeView.Nodes.Add(rootNode);
        }

        private static void FillTree(TreeNode treeNode, JToken jsonToken)
        {
            if (jsonToken.Type == JTokenType.Object)
            {
                foreach (JProperty child in jsonToken.Children<JProperty>())
                {
                    TreeNode childNode = new TreeNode(child.Name);
                    treeNode.Nodes.Add(childNode);
                    FillTree(childNode, child.Value);
                }
            }
            else if (jsonToken.Type == JTokenType.Array)
            {
                foreach (JToken item in jsonToken)
                {
                    TreeNode itemNode = new TreeNode(item.ToString());
                    treeNode.Nodes.Add(itemNode);
                    FillTree(itemNode, item);
                }
            }
            else
            {
                treeNode.Text = jsonToken.ToString();
            }
        }

        private void btnLoadJson_Click(object sender, EventArgs e)
        {
            treeView1.Nodes.Clear();
            OpenFileDialog openFileDialog = new OpenFileDialog();
            openFileDialog.Filter = "JSON files (*.json)|*.json";
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    //string json = File.ReadAllText(openFileDialog.FileName);
                    //JToken token = JToken.Parse(json);
                    //PopulateTreeView(token, null);

                    using (var reader = new StreamReader(openFileDialog.FileName))
                    using (var jsonReader = new JsonTextReader(reader))
                    {
                        root = JToken.Load(jsonReader);

                        //DisplayTreeView(root, "COVESA Vehicle Signal Specification REL 4.0");
                        DisplayTreeView(root, "COVESA Vehicle Signal Specification REL 4.0");
                    }

                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error loading JSON:" + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            //TreeView treeView = new TreeView();

        }

        private void DisplayTreeView(JToken root, string rootName)
        {
            treeView1.BeginUpdate();
            try
            {
                treeView1.Nodes.Clear();
                var tNode = treeView1.Nodes[treeView1.Nodes.Add(new TreeNode(rootName))];

                tNode.Tag = root;
                AddNode(root, tNode);

                //treeView1.ExpandAll();
                ExpandNodes(treeView1.Nodes, 0, 1);
            }
            finally
            {
                treeView1.EndUpdate();
            }
        }

        private void AddNode(JToken token, TreeNode inTreeNode)
        {
            if (token == null)
                return;
            if (token is JValue)
            {
                var childNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(token.ToString()))];
                childNode.Tag = token;
            }
            else if (token is JObject)
            {
                var obj = (JObject)token;
                //Check if it's leaf.
                if (obj.ContainsKey("datatype"))
                    return;

                foreach (var property in obj.Properties())
                {
                    switch (property.Name)
                    {
                        case "uuid":
                        case "uint":
                        case "type":
                        case "default":
                        case "comment":
                        case "description":
                            // Console.WriteLine("### IGNORE ####"+ property.Name);
                            break;
                        case "children":
                            JToken sub_jo = property.Value;

                            //Console.WriteLine("####"+sub_jo.ToString());
                            //PrintJsonTokenRecursively(sub_jo, indent + "  "); // 缩进以显示嵌套结构  
                            AddNode(property.Value, inTreeNode);
                            break;
                        default:
                            // Console.WriteLine($" {indent}{property.Name}:");
                            // PrintJsonTokenRecursively(property.Value, indent + "  "); // 缩进以显示嵌套结构  
                            var childNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(property.Name))];
                            childNode.Tag = property;
                            AddNode(property.Value, childNode);
                            break;
                    }

                }
            }
            else if (token is JArray)
            {
                var array = (JArray)token;
                for (int i = 0; i < 2;/* array.Count*/ i++)
                {
                    var childNode = inTreeNode.Nodes[inTreeNode.Nodes.Add(new TreeNode(i.ToString()))];
                    childNode.Tag = array[i];
                    AddNode(array[i], childNode);
                }
            }
            else
            {
                Debug.WriteLine(string.Format("{0} not implemented", token.Type)); // JConstructor, JRaw
            }
        }

        void ExpandNodes(TreeNodeCollection nodes, int depth, int maxDepth)
        {
            foreach (TreeNode node in nodes)
            {
                // 如果当前深度小于或等于最大深度，则展开节点  
                if (depth <= maxDepth)
                {
                    node.Expand(); // 展开节点  

                    // 如果需要继续展开下一级，则递归调用  
                    if (depth < maxDepth && node.Nodes.Count > 0)
                    {
                        ExpandNodes(node.Nodes, depth + 1, maxDepth);
                    }
                }
            }
        }

        private void treeView1_MouseDoubleClick(object sender, MouseEventArgs e)
        {

        }
        private string GetNodePath(TreeNode node)
        {
            if (node == null) return string.Empty;

            List<string> pathList = new List<string>();
            while (node != null)
            {
                pathList.Add(node.Text); // 将节点名称添加到列表的开头  
                node = node.Parent; // 向上移动到父节点  
            }

            // 反转列表以获取正确的路径顺序（从根到当前节点）  
            pathList.Reverse();
            pathList.RemoveAt(0);
            // 使用特定的分隔符（如"\"）连接路径列表中的字符串  
            string path = string.Join(".", pathList);

            return path;
        }

        private void treeView1_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            string path = GetNodePath(e.Node);
            string str2 = path.Replace(".", ".children.");
            JToken node = root.SelectToken(str2);

            int rowIndex = dataGridView1.Rows.Add();

            dataGridView1.Rows[rowIndex].Cells[0].Value = rowIndex;
            dataGridView1.Rows[rowIndex].Cells[1].Value = path;
            dataGridView1.Rows[rowIndex].Cells[2].Value = node["datatype"];
            dataGridView1.Rows[rowIndex].Cells[3].Value = node["type"];
            dataGridView1.Rows[rowIndex].Cells[4].Value = node["uuid"];
            dataGridView1.Rows[rowIndex].Cells[5].Value = node["description"];
            ScrollToLastLineAndFocus();
            //MessageBox.Show("Selected Node Path: " + node.ToString());
        }

        private void btnEnumTree_Click(object sender, EventArgs e)
        {
            EnumerateTreeViewNodes(treeView1, treeView1.Nodes);
        }
        void EnumerateTreeViewNodes(TreeView treeView, TreeNodeCollection nodes, string prefix = "")
        {
            foreach (TreeNode node in nodes)
            {
                // 输出当前节点的文本，带有前缀（用于表示层级）  
                //Console.WriteLine(prefix + node.Text);
                MessageBox.Show(prefix + node.Text);

                // 如果节点有子节点，则递归遍历它们  
                if (node.Nodes.Count > 0)
                {
                    // 为子节点添加前缀（通常是空格或制表符，用于缩进）  
                    string newPrefix = prefix + "  "; // 使用两个空格作为缩进示例  
                    EnumerateTreeViewNodes(treeView, node.Nodes, newPrefix);
                }
            }
        }

        private void treeView1_ItemDrag(object sender, ItemDragEventArgs e)
        {
            // 假设你只想拖动TreeNode对象  
            TreeNode node = e.Item as TreeNode;
            if (node != null)
            {
                // 设置拖放的数据，这里只是一个简单的示例，你可以传递更复杂的数据  
                //string dragData = node.Text;
                string dragData = GetNodePath(node);
                dataGridView2.DoDragDrop(dragData, DragDropEffects.Move);
            }
        }

        private void dataGridView2_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        private void dataGridView2_DragDrop(object sender, DragEventArgs e)
        {
            // 提取拖放的数据  
            string dragData = e.Data.GetData(typeof(string)) as string;
            if (dragData != null)
            {
                //int rowIndex = dataGridView2.Rows.Add();
                //dataGridView2.Rows[rowIndex].Cells[0].Value = 0;
                //dataGridView2.Rows[rowIndex].Cells[1].Value = dragData;
                //dataGridView2.Rows[rowIndex].Cells[2].Value = "VSS";

                // 获取鼠标在DataGridView上的位置  
                Point clientPoint = dataGridView2.PointToClient(new Point(e.X, e.Y));

                // 转换为单元格坐标  
                DataGridView.HitTestInfo hit = dataGridView2.HitTest(clientPoint.X, clientPoint.Y);

                // 检查是否命中了单元格  
                if (hit.Type == DataGridViewHitTestType.Cell)
                {
                    // 获取命中的单元格并更新其值  
                    dataGridView2[hit.ColumnIndex, hit.RowIndex].Value = dragData;
                }


            }
        }

        private void dataGridView2_DragOver(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Move;
        }

        private void ScrollToLastLineAndFocus()
        {
            int lastIndex = dataGridView1.Rows.Count - 1;
            //int lastVisibleIndex = Math.Max(0, lastIndex - dataGridView1.DisplayedRowCount(true));
            //dataGridView1.FirstDisplayedScrollingColumnIndex = lastVisibleIndex;
            if (lastIndex > 0)
            {
                dataGridView1.FirstDisplayedScrollingRowIndex = lastIndex;
            }
            dataGridView1.CurrentCell = dataGridView1.Rows[lastIndex - 1].Cells[0];
            dataGridView1.Rows[lastIndex - 1].Selected = true;
        }

        private void dataGridView1_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
        {
            // 假设你想要根据第一列的值来改变颜色  
            if (dataGridView1.Columns[e.ColumnIndex].Name == "Type" && e.Value != null)
            {
                // 将e.Value转换为适当的类型（例如string、int等）  
                string cellValue = e.Value.ToString();

                // 根据cellValue的值设置不同的背景色  
                switch (cellValue)
                {
                    case "sensor":
                        e.CellStyle.BackColor = Color.Yellow;
                        break;
                    case "actuator":
                        e.CellStyle.BackColor = Color.LightBlue;
                        break;
                    case "branch":
                        e.CellStyle.BackColor = Color.LightGreen;
                        break;
                    // ... 添加其他情况  
                    default:
                        //e.CellStyle.BackColor = dataGridView1.DefaultCellStyle.BackColor; // 设置为默认颜色  
                        e.CellStyle.BackColor = Color.LightGray;
                        break;
                }

            }
        }

        private void dataGridView2_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                // 获取点击位置的 DataGridViewHitTestInfo  
                DataGridView.HitTestInfo hit = dataGridView2.HitTest(e.X, e.Y);

                // 如果点击在行上或行单元格内，则显示上下文菜单  
                if (hit.Type == DataGridViewHitTestType.RowHeader ||
                    (hit.Type == DataGridViewHitTestType.Cell && hit.RowIndex >= 0))
                {
                    // 确保至少有一行被选中  
                    if (dataGridView2.SelectedRows.Count > 0)
                    {
                        contextMenuStrip.Show(dataGridView2, e.Location);
                    }
                }
            }
        }
    }

}
